(function(){
	// If we don't have our gaf object, create it now
	if ( typeof gaf == 'undefined' ) {
		gaf = {
			version: {
				major: 0,
				minor: 1,
				build: 0,
				type: 'Alpha',
				toString: function() {
					var v = this.major + '.' + this.minor + '.' + this.build;
					if ( typeof this.type != 'undefined' && this.type != null ) {
						v += ' (' + this.type + ')';
					}
					return v;
				}
			},
			config: {
				baseUrl: null
			},
			global: window
		}
		// Determine our root path
		var scripts = document.querySelectorAll('script[src$="gaf.js"]');
		if ( scripts && scripts.length > 0 ) {
			// We take the first gaf found
			var src = scripts[0].getAttribute('src');
			src = src.replace('gaf.js', '');
			gaf.config.baseUrl = src;
		}
	}
	/* -------------------------
	 * 	Fields
	 * ------------------------- */
	var _loadedModules = (_loadedModules || []);
	/* -------------------------
	 * 	Private Methods
	 * ------------------------- */
	// TODO: Make private
	gaf._getScriptSource = function(src) {
		var http = new XMLHttpRequest();
		http.open('GET', src, false);
		http.send();
		if ( !gaf._checkXhrStatus(http) ) {
			var error = new Error('Unable to load source file "' + src + '" for include.');
			error.status = http.status;
			error.responseText = http.responseText;
			throw error;
		}
		return http.responseText;
	};
	// TODO: Make private
	gaf._checkXhrStatus = function(xhr) {
		var status = xhr.status || 0;
		return (status >= 200 && status < 300) || status == 304 || status == 1223;
	};
	// TODO: Make private
	gaf._isModuleLoaded = function(pkg) {
		var mod = _loadedModules[pkg];
		var loaded = false;
		if ( mod ) {
			loaded = true;
		} else {
			// Check to see if it was loaded manually through <script /> tags
			var scripts = document.querySelectorAll('script[src="' + pkg + '"]');
			loaded = scripts && scripts.length > 0;
		}
		return loaded;
	}
	/* -------------------------
	 * 	Public Methods
	 * ------------------------- */
	gaf.requires = function(pkg) {
		// TODO: Remove assumption that baseUrl will have a trailing /
		var path = (pkg.split('.').join('/') + '.js').toLowerCase();
		if ( gaf.config.baseUrl != null && typeof gaf.config.baseUrl != 'undefined' ) {
			if (path.indexOf('gaf' >= 0)) {
				path = path.replace('gaf/', gaf.config.baseUrl);
			}
			else {
				path = gaf.config.baseUrl + path;
			}
		}
		// Check to make sure we're not already loaded
		if ( gaf._isModuleLoaded(path) ) {
			return this;
		}
		// Load our module
		var src = gaf._getScriptSource(path);
		if ( src ) {
			// TODO: Add scoping
			gaf.global.eval(src);
			_loadedModules[pkg] = true;
			_loadedModules.push(pkg);
		}
		return this;
	};
})();
